package clientes;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.joda.time.DateTime;

import ofertas.Oferta;
import pedidos.Pedido;
import productosYPresentaciones.Producto;
import sucursal.Stock;
import cadenaDeSucursales.CadenaSucursales;

/**
 * Clase que representa a cada cliente de CadenaSucursales junto a sus funcionalidades.
 * Se implementa el patron Observer de dos maneras distintas, en la primera es un observer
 * comun, donde el obsrvable es CadenaSucursales y esta clase es el observer; y en la segunda
 * es un observer m�s complejo, con un intermediario, donde el observable es el producto, 
 * el change manager o mediador es sucursal y la presente clase es la clase observer.
 * @author Stefania Lilian Chiniewicz
 */

public class Cliente {

	private Stock ccProductos;
	private float ccPesos;
	private String dni;
	private String domicilio;
	private String email;
	private List<Oferta> bandejaDeEntrada;
	private List<Ticket>tickets;
	private List<Ticket>ticketsCCPesos;
	private List <TicketCcProductos> detalleRetiroEntrega;
	
	/**
	 * Constructor de la clase Cliente.
	 * @param dni
	 * @param domicilio
	 * @param email
	 */
	
	public Cliente(String dni, String domicilio, String email) {
		this.ccProductos = new Stock();
		this.ccPesos = 0f;
		this.dni = dni;
		this.domicilio = domicilio;
		this.email = email;
		this.bandejaDeEntrada = new ArrayList<Oferta>();
		this.tickets= new ArrayList<Ticket>();
		this.ticketsCCPesos= new ArrayList<Ticket>();
		this.detalleRetiroEntrega= new ArrayList<TicketCcProductos>();
	}
/**
 * Getters y setters!!
 */
	
	public List<Ticket> getTicketsCCPesos() {
		return ticketsCCPesos;
	}

	protected void setTicketsCCPesos(List<Ticket> ticketsCCPesos) {
		this.ticketsCCPesos = ticketsCCPesos;
	}

	public List<TicketCcProductos> getDetalleRetiroEntrega() {
		return detalleRetiroEntrega;
	}

	protected  void setTickets(List<Ticket> tickets) {
		this.tickets = tickets;
	}
	
	public List<Ticket> getTickets() {
		return this.tickets;
	}

	public Stock getCcProductos() {
		return ccProductos;
	}

	protected void setCcProductos(Stock s) {
		this.ccProductos = s;
	}

	public float getCcPesos() {
		return ccPesos;
	}

	protected  void setCcPesos(float ccPesos) {
		this.ccPesos = ccPesos;
	}

	public String getDomicilio() {
		return domicilio;
	}

	protected void setDomicilio(String domicilio) {
		this.domicilio = domicilio;
	}

	public String getEmail() {
		return email;
	}

	protected  void setEmail(String email) {
		this.email = email;
	}

	public List<Oferta> getBandejaDeEntrada() {
		return bandejaDeEntrada;
	}

	protected void setBandejaDeEntrada(List<Oferta> bandejaDeEntrada) {
		this.bandejaDeEntrada = bandejaDeEntrada;
	}
	
	public String getDni() {
		return dni;
	}
	
	/***
	 * le agrega credito a mi cuenta corriente.
	 * @param p: el importe a agregar a mi cta cte.
	 */
	public void agregarACuentaCorrientePesos(float p){
		this.setCcPesos(this.getCcPesos()+p);
	}
	
	/***
	 * Le agrega un stock a que puedo comprar a la variable existente
	 * @param p: el producto a agregar a mi cta cte de productos.
	 * @param cant: la cantidad del producto que vamos a agregar.
	 */
	public void agregarACuentaCorrienteProductos(Producto p, int cant){
		this.getCcProductos().agregarStock(p, cant);
	}
	
	/***
	 * Agrega el ticket de la �ltima compra a la lista de tickets que tiene el usuario.
	 * @param t: el ticket a agregar en la lista.
	 */
	
	public void recibirTicket(Ticket t){
		this.getTickets().add(t);
	}


	/**
	 * Agrega el detalle de compra de las compras con cta cte pesos.
	 * @param dc: el detalle de compra a agregar.
	 */
	public void recibirDetalleCompra(Ticket dc){
		this.getTicketsCCPesos().add(dc);
	}
	
	/**
	 * Agrega el detalle de retiro/entrega de las compras a domicilio.
	 * @param dre:el detalle de retiro/entrega
	 */
	public void recibirDetalleRetiroEntrega(TicketCcProductos dre){
		this.getDetalleRetiroEntrega().add(dre);
	}

	
	///////Metodos del primer observer///////

/**
 * M�todo que recibe la oferta nueva de cadenaSucursales y la agrega a la bandejaDeEntrada con el m�todo privado
 * "agregarAListaDeOfertasRecibidas(Oferta o)"
 * @param cadenaSucursales
 * @param o: 
 */
	
	public void recibirNotificacionOfertas(CadenaSucursales cadenaSucursales, Oferta o) {
		// TODO Auto-generated method stub
		this.agregarAListaDeOfertasRecibidas(o);
	}
	
	/**
	 * Agrega a la bandeja de entrada una oferta nueva.
	 * @param o:oferta que se agrega a la "bandeja de entrada"
	 */

	private void agregarAListaDeOfertasRecibidas(Oferta o) {
		// TODO Auto-generated method stub
		this.getBandejaDeEntrada().add(o);
	}
	//////////////////////
	
	
	////Metodo del segundo observer.///////

	public void notificarPedidoCompleto(Pedido p) {
		//se deja en to-do porque no hay especificacion de que hacer cuando se 
		//se le notifica que su pedido esta completo.
		
	}
	
	/////////////////////////////

   //////////// Mensajes implementados por necesidad de Venta//////////
	
	public boolean puedePagarProducto(Producto unProducto) {
	
		return this.getCcPesos() >= unProducto.precioActual();
		
	}
	/**
	 * Revisa si el producto est� en la ccProductos del cliente.
	 * @param unProducto
	 * @param cantidad
	 * @return true o false si
	 */
	public boolean elProductoEstaEnCCProductos(Producto unProducto, int cantidad){
		return this.getCcProductos().hayStock(unProducto, cantidad);
	}

	/**
	 * Descuenta de la cuenta corriente pesos el monto
	 * pasado por par�metro.
	 * @param precioDelProducto
	 */

	public void descontarDeCCPesos(float precioDelProducto) {
		setCcPesos(this.getCcPesos()-precioDelProducto);
	}

/**
 * Descuenta de la ccProductos el producto con su cantidad.
 * @param unProducto
 * @param cantidad
 */
	public void descontarDeCCProductos(Producto unProducto, int cantidad) {
		getCcProductos().quitarStock(unProducto, cantidad);
		
	}

	/**
	 * Verifica si se puede pagar el monto pasado
	 * por parametro.
	 * @param montoAPagar monto que debe ser pagado.
	 * @return si puede pagar el monto.
	 */
	public boolean puedePagarElMontoDesdeCCPesos(float montoAPagar) {
		return this.getCcPesos() >= montoAPagar;
	}
	
	/**
	 * se verificara si se pueden comprar los productos
	 * a traves de la cuenta corriente en productos.
	 * @param unosProductos productos a ser verificados
	 * @return si puede pagar los productos.
	 */
	public boolean puedePagarLosProductosDesdeCCProductos(
			Map<Producto, Integer> unosProductos) {
		Set<Map.Entry<Producto, Integer>> productos = unosProductos.entrySet();
		boolean puedePagar = false;
		 for (Map.Entry<Producto, Integer> productoActual : productos) {
			 puedePagar = puedePagar | (this.elProductoEstaEnCCProductos(
					 productoActual.getKey(),
					 unosProductos.get(productoActual.getKey())));
		    }
		return puedePagar;
		}

	/**
	 * removera de la cuenta corriente unos productos.
	 * @param unosProductos son los productos comprados a remover.
	 */
	public void descontarDeCCProductos(Map<Producto, Integer> unosProductos) {
		Set<Map.Entry<Producto, Integer>> productos = unosProductos.entrySet();
		for (Map.Entry<Producto, Integer> productoActual : productos) {
			this.descontarDeCCProductos(productoActual.getKey(), productoActual.getValue());
		}	
	}
}
